package server;


import java.io.File;
import utils.LogUtils;
import java.util.Scanner;
import security.Signature;
import database.Database;
import java.io.FileReader;
import java.util.Properties;
import java.io.IOException;
import security.CipherFile;
import security.SealedObj;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.sql.SQLException;
import security.SealedObjAES;
import security.CipherFileAES;
import security.SignatureSHA1;
import database.DatabaseMysql;
import constans.ErrorConstants;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;


public class Server {


    private Logger  logger;
    private String  filename;
    private Process process;


    public Server(String filename) {
        this.filename = filename;
    }


    public void run() {        
        loadConfiguration();
        startProcess();
        menu();
    }


    private void loadConfiguration() {

        try {
            logger = LogUtils.getLogger("rArcServer", "rArcServer.log");
        } catch (IOException ex) {
            //TODO
            System.exit(1);
        }

        Properties properties = new Properties();
        try {
            properties.load(new FileReader(filename));
        } catch (IOException ex) {
            logger.log(Level.SEVERE, "Error code ("+ErrorConstants.ERROR_CONFIGURATION_FILE+"): "+ex.getMessage());
            System.exit(ErrorConstants.ERROR_CONFIGURATION_FILE);
        }

        File folderCapsule = new File(properties.getProperty("FolderCapsule"));


        CipherFile cipher     = null;
        SealedObj sealdObj = null;;
        try {
            cipher     = new CipherFileAES(properties.getProperty("PassCipher").getBytes("UTF-8"));
            sealdObj = new SealedObjAES(properties.getProperty("PassCipher").getBytes("UTF-8"));
        } catch (GeneralSecurityException ex) {
           logger.log(Level.SEVERE, "Error code("+ErrorConstants.ERROR_CIPHER_PASSWORD+"): "+ex.getMessage());
           System.exit(ErrorConstants.ERROR_CIPHER_PASSWORD);
        } catch (UnsupportedEncodingException ex) {
          //TODO
          System.exit(1);
        }


        Signature signature = null;
        try {
            signature = new SignatureSHA1(properties.getProperty("PassSignature").getBytes("UTF-8"));
        } catch (GeneralSecurityException ex) {
            logger.log(Level.SEVERE, "Error code("+ErrorConstants.ERROR_SIGNATURE_PASSWORD+"): "+ex.getMessage());
            System.exit(ErrorConstants.ERROR_SIGNATURE_PASSWORD);
        } catch (UnsupportedEncodingException ex) {
            //TODO
            System.exit(1);
        }


        ServerState serverState = null;
        try{
            serverState = ServerState.valueOf(properties.getProperty("ServerState"));
        } catch(Exception ex){
            logger.log(Level.SEVERE, "Error code ("+ErrorConstants.ERROR_SERVER_STATE+"): "+ex.getMessage());
            System.exit(ErrorConstants.ERROR_SERVER_STATE);
        }

        
        int portServer = 0;
        try{
            portServer = Integer.parseInt(properties.getProperty("ServerPort"));
        } catch(Exception ex){
            //TODO
            System.exit(1);
        }


        int maxReplication = 0;
        try{
            maxReplication = Integer.parseInt(properties.getProperty("MaxReplication"));
        } catch(Exception ex){
            //TODO
            System.exit(1);
        }        


        Database database = new DatabaseMysql(properties.getProperty("DatabaseHost"),
            properties.getProperty("DatabaseUser"), properties.getProperty("DatabasePass"),
            properties.getProperty("DatabaseName"));

        
        int maxUsers = 0;
        try{
            maxUsers = Integer.parseInt(properties.getProperty("MaxClients"));
        } catch(Exception ex){
           //TODO
            System.exit(1);
        }

        try {
            if (serverState.equals(ServerState.REPLICATION)) {
                process = new ReplicationManager(database, signature, sealdObj, portServer, maxUsers,
                        folderCapsule, logger, maxReplication);
            } else if (serverState.equals(ServerState.RECOVERY)) {
                File folderCapsuleTemporary = new File(properties.getProperty("FolderCapsuleTemporary"));
                process = new RecuperationManager(database, signature, sealdObj, cipher, portServer,
                        maxUsers,folderCapsule,folderCapsuleTemporary, logger);
            }
       } catch (SQLException ex) {
            logger.log(Level.SEVERE, "Error code("+ErrorConstants.ERROR_DATABASE+"): "+ex.getMessage());
            System.exit(ErrorConstants.ERROR_DATABASE);
       }
    }


    private void startProcess() {
        logger.log(Level.INFO,"rARC Server is runnning...Press '0' and [Enter] to stop rARC Server.");
        process.start();
    }


    private void menu() {
    
        Scanner inputKeyboard = new Scanner(System.in);
        int option;

        while (true) {
            try {
                option = Integer.parseInt(inputKeyboard.next());

                if (option == 0) {
                     logger.log(Level.INFO,"Stop rARC Server");

                    if (process.isAlive()) {
                        process.stopRun();
                    }
                    break;
                } 
            } catch (NumberFormatException e) {}
        }

        System.exit(0);
    }

    
    public static void main(String[] args) {
        if (args.length != 1) {
            System.out.println("Sintaxe: java Server <configuration filename>");
        } else {
            new Server(args[0]).run();
        }
    }


}
